/*------------------------------------------------------------------------
   io3731.c - io pin functios of the EnE IO3771 EC

   Copyright (C) 2011 One Laptop per Child

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2, or (at your option) any
   later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

   In other words, you are welcome to use, share and improve this program.
   You are forbidden to forbid anyone else to use, share and improve
   what you give them.   Help stamp out software-hoarding!

   As a special exception, you may use this file as part of a free software
   library for the XO of the One Laptop per Child project without restriction.
   Specifically, if other files instantiate
   templates or use macros or inline functions from this file, or you compile
   this file and link it with other files to produce an executable, this
   file does not by itself cause the resulting executable to be covered by
   the GNU General Public License.  This exception does not however
   invalidate any other reasons why the executable file might be covered by
   the GNU General Public License.
-------------------------------------------------------------------------*/

#include <stdio.h>
#include "cc_compat.h"
#include "io.h"
#include "timer.h"
#include "power.h"
#include "adc.h"
#include "uart.h"
#include "charger.h"

#if OPT_PRAGMA
#pragma ot(9,speed)
#endif

unsigned char data board_rev;

#define PWM_8_BIT_MAX	255
#define PWM_12_BIT_MAX	4095
#define PWM_14_BIT_MAX	16383

// PWM0 is special it has 16 bits of high
// and 16bits of low.  The sum of the 2 is
// the period.
// PWM clock by default is 16Mhz or 62.5ns
// 533 is just over 30kHz
#define PWM0_PERIOD		533

#define LED_BAT_G_PWM		3
#define LED_BAT_R_PWM		1
#define CHRG_BAT_PWM		2

// Deal with the pwm signals
// Channel 0 is UART TX so don't mess with that channel
void set_pwm(unsigned char channel,unsigned int value)
{
	unsigned int low;

	// In order to turn off the PWMs you have to enable the output
	// and drive it low.
	// Set the value to zero so that the pwm_read() can
	// see when its off
	if (value == 0)
	{
		switch (channel)
		{
#if 0
			case 0:
				PWMHIGH0 = 0;
				IO_ALT_OUT_DISABLE(GPIO_0F);		// Turn off PWM
				IO_OUTPUT_LOW(GPIO_0F);				// Drive it low.
				break;
			case 1:
				PWMHIGH1 = 0;
				IO_ALT_OUT_DISABLE(GPIO_10);		// Turn off PWM
				IO_OUTPUT_LOW(GPIO_10);				// Drive it low.
				break;
#endif
			case 2:
				PWM2HIGHH = 0;
				PWM2HIGHL = 0;
				IO_ALT_OUT_DISABLE(GPIO_15);		// Turn off PWM
				IO_OUTPUT_LOW(GPIO_15);				// Drive it low.
				break;
#if 0
			case 3:
				PWMHIGH3H = 0;
				PWMHIGH3L = 0;
				IO_ALT_OUT_DISABLE(GPIO_19);		// Turn off PWM
				IO_OUTPUT_LOW(GPIO_19);				// Drive it low.
				break;
#endif
		}
	}
	// Normal pwm operation.
	else
	{
		switch (channel)
		{
			case 0:
				if (value > PWM0_PERIOD )
				{
					value = PWM0_PERIOD;
				}
				low = PWM0_PERIOD - value;

				PWM0HIGHH	= value >> 8;
				PWM0HIGHL	= value;

				PWM0LOWH	= low >> 8;
				PWM0LOWL	= low;

				break;
#if 0

			case 1:
				PWMHIGH1 = value;
				IO_ALT_OUT_ENABLE(GPIO_10);		// Turn on the PWM output in case it was off previously
				break;
#endif
			case 2:
				PWM2HIGHH = value>>8;
				PWM2HIGHL = value;
				IO_ALT_OUT_ENABLE(GPIO_15);		// Turn on the PWM output in case it was off previously
				break;
#if 0
			case 3:
				PWMHIGH3H = value>>8;
				PWMHIGH3L = value;
				IO_ALT_OUT_ENABLE(GPIO_19);		// Turn on the PWM output in case it was off previously
				break;
#endif
		}
	}
}

#ifdef UNUSED
unsigned int read_pwm(unsigned char channel)
{
	switch (channel)
	{
#if 0

		case 0:
			return (unsigned int)PWMHIGH0;
		case 1:
			return (unsigned int)PWMHIGH1;
#endif
		case 2:
			return ((unsigned int)PWM2HIGHH<<8)|PWM2HIGHL;
#if 0
		case 3:
			return ((unsigned int)PWMHIGH3H<<8)|PWMHIGH3L;
		case 4:
			return ((unsigned int)FANPWMH0<<8)|FANPWML0;
		case 5:
			return ((unsigned int)FANPWMH1<<8)|FANPWML1;
#endif
	}
//	puts("unknown pwm read");
	return 0;
}
#endif


//============================================
#if ! USE_MACROS_FOR_IO

void set_LED_PWR_on(void)
{
	IO_OUTPUT_HIGH(GPIO_19);
}
void set_LED_PWR_off(void)
{
	IO_OUTPUT_LOW(GPIO_19);
}
#if 0
void set_LED_PWR(unsigned int value)
{
	set_pwm(LED_PWR_PWM,value);
}
#endif

void output_enable_LED_PWR(void)
{
	IO_OUTPUT_ENABLE(GPIO_19);
}
void output_disable_LED_PWR(void)
{
	IO_OUTPUT_DISABLE(GPIO_19);
}

void set_LED_CHG_RED_on(void)
{
	IO_OUTPUT_HIGH(GPIO_07);
//	set_pwm(LED_BAT_R_PWM,PWM_8_BIT_MAX);
}
void set_LED_CHG_RED_off(void)
{
	IO_OUTPUT_LOW(GPIO_07);
//	set_pwm(LED_BAT_R_PWM,0);
}

void output_enable_LED_CHG_RED(void)
{
	IO_OUTPUT_ENABLE(GPIO_07);
}
void output_disable_LED_CHG_RED(void)
{
	IO_OUTPUT_DISABLE(GPIO_07);
}


void input_enable_SOC_SLEEP(void)
{
	IO_INPUT_ONLY(GPIO_0B);
}


void set_LED_CHG_GREEN_on(void)
{
	IO_OUTPUT_HIGH(GPIO_16);
//	set_pwm(LED_BAT_G_PWM,PWM_8_BIT_MAX);
}
void set_LED_CHG_GREEN_off(void)
{
	IO_OUTPUT_LOW(GPIO_16);
//	set_pwm(LED_BAT_G_PWM,0);
}

void output_enable_LED_CHG_GREEN(void)
{
	IO_OUTPUT_ENABLE(GPIO_16);
}
void output_disable_LED_CHG_GREEN(void)
{
	IO_OUTPUT_DISABLE(GPIO_16);
}

void set_LED_CHG_RED(unsigned int value)
{
	set_pwm(LED_BAT_R_PWM,value);
}

void set_LED_CHG_GREEN(unsigned int value)
{
	set_pwm(LED_BAT_G_PWM,value);
}

// Inputs
unsigned char read_CHRG_AC_OK(void)
{
	return IO_ACTIVE_HIGH(GPIO_23);
}

void input_enable_CHRG_AC_OK(void)
{
	IO_INPUT_ONLY(GPIO_23);
}

unsigned char read_CHRG_VOL_SEL(void)
{
	return IO_ACTIVE_HIGH(GPIO_29);
}
void input_enable_CHRG_VOL_SEL(void)
{
	IO_INPUT_ENABLE(GPIO_29);
}

#if 0
unsigned char read_PCI_RST(void)
{
	return IO_ACTIVE_LOW(GPIO_04);
}
unsigned char readport_KEY_IN(unsigned char mask)
{
	return IO_PORT_READ(GPIO_PORT_0,mask);
}
#endif

unsigned char read_PWR_BTN(void)
{
	return IO_ACTIVE_LOW(GPIO_2A);
}
void input_enable_PWR_BTN(void)
{
	IO_INPUT_ONLY(GPIO_2A);
}

unsigned char read_ALL_PWRGOOD(void)
{
	return IO_ACTIVE_HIGH(GPIO_1C);
}
void input_enable_ALL_PWRGOOD(void)
{
	IO_INPUT_ONLY(GPIO_1C);
}

unsigned char read_SYS_RESET(void)
{
	return IO_ACTIVE_LOW(GPIO_1B);
}
void input_enable_SYS_RESET(void)
{
	IO_INPUT_ONLY(GPIO_1B);
}

void input_enable_CHRG_DQ(void)
{
	IO_INPUT_ENABLE(GPIO_06);
}

unsigned char read_RESTORE(void)
{
	return IO_ACTIVE_LOW(GPIO_31);
}
void input_enable_RESTORE(void)
{
	IO_INPUT_ONLY(GPIO_31);
}

unsigned char read_PWR_LMT_ON(void)
{
	return IO_ACTIVE_LOW(GPIO_03);
}
void input_enable_PWR_LMT_ON(void)
{
	IO_INPUT_ONLY(GPIO_03);
}

//============================================

void enable_EN_MAIN_PWR(void)
{
	IO_OUTPUT_HIGH(GPIO_24);
}
void disable_EN_MAIN_PWR(void)
{
	IO_OUTPUT_LOW(GPIO_24);
}
void output_enable_EN_MAIN_PWR(void)
{
	IO_OUTPUT_ENABLE(GPIO_24);
}
void output_disable_EN_MAIN_PWR(void)
{
	IO_OUTPUT_DISABLE(GPIO_24);
}

void enable_EN_VCORE_PWR(void)
{
	IO_OUTPUT_HIGH(GPIO_17);
}
void disable_EN_VCORE_PWR(void)
{
	IO_OUTPUT_LOW(GPIO_17);
}
void output_enable_EN_VCORE_PWR(void)
{
	IO_OUTPUT_ENABLE(GPIO_17);
}
void output_disable_EN_VCORE_PWR(void)
{
	IO_OUTPUT_DISABLE(GPIO_17);
}


void enable_EN_1_8V_PMIC(void)
{
	IO_OUTPUT_LOW(GPIO_1F);
}
void disable_EN_1_8V_PMIC(void)
{
	IO_OUTPUT_HIGH(GPIO_1F);
}
void output_enable_EN_1_8V_PMIC(void)
{
	IO_OUTPUT_ENABLE(GPIO_1F);
}
void output_disable_EN_1_8V_PMIC(void)
{
	IO_OUTPUT_DISABLE(GPIO_1F);
}

void enable_EN_SD1_PWR(void)
{
	IO_OUTPUT_LOW(GPIO_20);
}
void disable_EN_SD1_PWR(void)
{
	IO_OUTPUT_HIGH(GPIO_20);
}
void output_enable_EN_SD1_PWR(void)
{
	IO_OUTPUT_ENABLE(GPIO_20);
}
void output_disable_EN_SD1_PWR(void)
{
	IO_OUTPUT_DISABLE(GPIO_20);
}

void enable_EN_SD2_PWR(void)
{
	IO_OUTPUT_LOW(GPIO_21);
}
void disable_EN_SD2_PWR(void)
{
	IO_OUTPUT_HIGH(GPIO_21);
}
void output_enable_EN_SD2_PWR(void)
{
	IO_OUTPUT_ENABLE(GPIO_21);
}
void output_disable_EN_SD2_PWR(void)
{
	IO_OUTPUT_DISABLE(GPIO_21);
}

void enable_EN_1_8V_GPIO(void)
{
	IO_OUTPUT_LOW(GPIO_04);
}
void disable_EN_1_8V_GPIO(void)
{
	IO_OUTPUT_HIGH(GPIO_04);
}
void output_enable_EN_1_8V_GPIO(void)
{
	IO_OUTPUT_ENABLE(GPIO_04);
}
void output_disable_EN_1_8V_GPIO(void)
{
	IO_OUTPUT_DISABLE(GPIO_04);
}

void enable_EN_3_3V_SOC(void)
{
	IO_OUTPUT_LOW(GPIO_22);
}
void disable_EN_3_3V_SOC(void)
{
	IO_OUTPUT_HIGH(GPIO_22);
}
void output_enable_EN_3_3V_SOC(void)
{
	IO_OUTPUT_ENABLE(GPIO_22);
}
void output_disable_EN_3_3V_SOC(void)
{
	IO_OUTPUT_DISABLE(GPIO_22);
}

void enable_EN_3_3V_NAND(void)
{
	IO_OUTPUT_LOW(GPIO_26);
}
void disable_EN_3_3V_NAND(void)
{
	IO_OUTPUT_HIGH(GPIO_26);
}
void output_enable_EN_3_3V_NAND(void)
{
	IO_OUTPUT_ENABLE(GPIO_26);
}
void output_disable_EN_3_3V_NAND(void)
{
	IO_OUTPUT_DISABLE(GPIO_26);
}


void enable_EC_IRQ(void)
{
	IO_OUTPUT_LOW(GPIO_18);
}
void disable_EC_IRQ(void)
{
	IO_OUTPUT_HIGH(GPIO_18);
}
void output_enable_EC_IRQ(void)
{
	IO_OUTPUT_EC_IRQ(GPIO_18);
}
void output_disable_EC_IRQ(void)
{
	IO_OUTPUT_DISABLE(GPIO_18);
}


void enable_EN_DCON_PWR(void)
{
	IO_OUTPUT_LOW(GPIO_1A);
}
void disable_EN_DCON_PWR(void)
{
	IO_OUTPUT_HIGH(GPIO_1A);
}
void output_enable_EN_DCON_PWR(void)
{
	IO_OUTPUT_ENABLE(GPIO_1A);
}
void output_disable_EN_DCON_PWR(void)
{
	IO_OUTPUT_DISABLE(GPIO_1A);
}

void enable_EN_1_5V_DDR3(void)
{
	IO_OUTPUT_HIGH(GPIO_27);
}
void disable_EN_1_5V_DDR3(void)
{
	IO_OUTPUT_LOW(GPIO_27);
}
void output_enable_EN_1_5V_DDR3(void)
{
	IO_OUTPUT_ENABLE(GPIO_27);
}
void output_disable_EN_1_5V_DDR3(void)
{
	IO_OUTPUT_DISABLE(GPIO_27);
}

void enable_EN_1_2V(void)
{
	IO_OUTPUT_HIGH(GPIO_28);
}
void disable_EN_1_2V(void)
{
	IO_OUTPUT_LOW(GPIO_28);
}
void output_enable_EN_1_2V(void)
{
	IO_OUTPUT_ENABLE(GPIO_28);
}
void output_disable_EN_1_2V(void)
{
	IO_OUTPUT_DISABLE(GPIO_28);
}

void enable_SOC_RESET(void)
{
	IO_OUTPUT_LOW(GPIO_02);
}
void disable_SOC_RESET(void)
{
	IO_OUTPUT_HIGH(GPIO_02);
}
void output_enable_SOC_RESET(void)
{
	IO_OPEN_DRAIN_ENABLE(GPIO_02);
	IO_OUTPUT_ENABLE(GPIO_02);
}

void enable_EN_USB_PWR(void)
{
	IO_OUTPUT_HIGH(GPIO_05);
}
void disable_EN_USB_PWR(void)
{
	IO_OUTPUT_LOW(GPIO_05);
}
void output_enable_EN_USB_PWR(void)
{
	IO_OUTPUT_ENABLE(GPIO_05);
}
void output_disable_EN_USB_PWR(void)
{
	IO_OUTPUT_DISABLE(GPIO_05);
}

void enable_CHRG_VOL_SEL(void)
{
	IO_OUTPUT_HIGH(GPIO_29);
}
void disable_CHRG_VOL_SEL(void)
{
	IO_OUTPUT_LOW(GPIO_29);
}
void output_enable_CHRG_VOL_SEL(void)
{
	IO_OUTPUT_ENABLE(GPIO_29);
}
void output_disable_CHRG_VOL_SEL(void)
{
	IO_OUTPUT_DISABLE(GPIO_29);
}

void enable_CHRG_DQ(void)
{
	IO_OUTPUT_LOW(GPIO_06);
}
void disable_CHRG_DQ(void)
{
	IO_OUTPUT_HIGH(GPIO_06);
}
void output_enable_CHRG_DQ(void)
{
	IO_OUTPUT_ENABLE(GPIO_06);
}
void output_disable_CHRG_DQ(void)
{
	IO_OUTPUT_DISABLE(GPIO_06);
}


//==================================================

void enable_CHRG_TRICKLE(void)
{
	IO_OUTPUT_HIGH(GPIO_30);
}
void disable_CHRG_TRICKLE(void)
{
	IO_OUTPUT_LOW(GPIO_30);
}
void output_enable_CHRG_TRICKLE(void)
{
	IO_OUTPUT_ENABLE(GPIO_30);
}

// OLS# is actually a gate for the WLAN led it has nothing to do with
// if OLS is actually up and running.
// Its badly named by quanta.
void enable_LED_INHIBIT(void)
{
	IO_OUTPUT_LOW(GPIO_29);
}

void disable_LED_INHIBIT(void)
{
	IO_OUTPUT_HIGH(GPIO_29);
}

void output_enable_LED_INHIBIT(void)
{
	IO_OUTPUT_ENABLE(GPIO_29);
}

#endif  // USE_MACROS_FOR_IO

void enable_EN_KBD_PWR(void)
{
	IO_OUTPUT_LOW(GPIO_32);
}
void disable_EN_KBD_PWR(void)
{
	IO_OUTPUT_HIGH(GPIO_32);
}
void output_enable_EN_KBD_PWR(void)
{
	IO_OUTPUT_ENABLE(GPIO_32);
}
void output_disable_EN_KBD_PWR(void)
{
	IO_OUTPUT_DISABLE(GPIO_32);
}

void pwm_init(void)
{

#if 0
	// Set C to 0xfe so that when you set H = 0xff you get a full 1
	// output = 1 when H > C
	// 8-bit
	pwm[PWMHIGH0] = 0x00;
	pwm[PWMCYCL0] = 0xFE;

	pwm[PWMHIGH1] = 0x00;
	pwm[PWMCYCL1] = 0xFE;

	pwm[PWMHIGH3H] = 0x00;
	pwm[PWMHIGH3L] = 0x00;
	pwm[PWMCYC3H] = 0x3F;
	pwm[PWMCYC3L] = 0xFE;

	// TODO: Look at these signals with a scope
	// Do we save any power by using slower PWM frequency?
	pwm[PWMCFG]  = 0x11;				// Enable PWM 0,1. Period 1us.
	pwm[PWMCFG2] = 0xC0;				// enable PWMs 2,3, 1Mhz clock
	pwm[PWMCFG3] = 0xC0;

	set_pwm(1,0);
	set_pwm(3,0);
	set_pwm(4,0);

	set_pwm(0,PWM0_PERIOD);

	// Enable PWM 0,2; push pull
	PWMCFG = 0x05;

	//	IO_ALT_OUT_ENABLE(GPIO_07);
	//	IO_ALT_OUT_ENABLE(GPIO_16);
#endif
}

void pwm_2_init(void)
{
	set_pwm(2,0);
	PWM2CYCH = 0x0f;
	PWM2CYCL = 0xFE;
	// Enabled and push pull
	PWMCFG |= 0x04;

	IO_ALT_OUT_ENABLE(GPIO_15);
}

// This is the default IO map for the 1.75 A2
void init_default_io(void)
{
	disable_EN_MAIN_PWR();
	output_enable_EN_MAIN_PWR();

	disable_EN_VCORE_PWR();
	output_enable_EN_VCORE_PWR();

	disable_EN_1_8V_PMIC();
	output_enable_EN_1_8V_PMIC();

	disable_EN_1_8V_GPIO();
	output_enable_EN_1_8V_GPIO();

	disable_EN_3_3V_SOC();
	output_enable_EN_3_3V_SOC();

	disable_EN_3_3V_NAND();
	output_enable_EN_3_3V_NAND();

	disable_EN_KBD_PWR();
	output_enable_EN_KBD_PWR();

	disable_EN_DCON_PWR();
	output_enable_EN_DCON_PWR();

	disable_EC_IRQ();
	output_enable_EC_IRQ();

	disable_EN_1_5V_DDR3();
	output_enable_EN_1_5V_DDR3();

	disable_EN_1_2V();
	output_enable_EN_1_2V();

	disable_EN_USB_PWR();
	output_enable_EN_USB_PWR();

	disable_CHRG_TRICKLE();
	output_enable_CHRG_TRICKLE();

	disable_EN_SD1_PWR();
	output_enable_EN_SD1_PWR();

	disable_EN_SD2_PWR();
	output_enable_EN_SD2_PWR();

	// This turns off the WLAN LED inhibit signal
	disable_LED_INHIBIT();
	output_enable_LED_INHIBIT();

	// CHRG_DQ is active low; the 1-wire code
	// keeps the signal low and just flips the
	// enable
	enable_CHRG_DQ();

	// Not a typo.  System is in reset
	// when active.
	enable_SOC_RESET();
	output_enable_SOC_RESET();

	input_enable_PWR_BTN();
	input_enable_ALL_PWRGOOD();
	input_enable_SYS_RESET();
	input_enable_CHRG_DQ();
	input_enable_CHRG_AC_OK();
	input_enable_PWR_LMT_ON();
	input_enable_SOC_SLEEP();

	/* the default role of GPIO2D and GPIO2E is SDA0/SCL0.  turn
	 * them into input-only non-interrupt gpios for now.
	 */
	IO_ALT_OUT_DISABLE(GPIO_2D);
	IO_INPUT_ONLY(GPIO_2D);
	IO_WAKEUP_DISABLE(GPIO_2D);

	IO_ALT_OUT_DISABLE(GPIO_2E);
	IO_INPUT_ONLY(GPIO_2E);
	IO_WAKEUP_DISABLE(GPIO_2E);

	/* disable unused SMBus controllers */
	SMBDCFG &= ~0x07;
	SMS0CFG &= ~0x07;
	SMS1CFG &= ~0x07;

	SMB0CFG |= 0xc0;
	SMB1CFG |= 0xc0;

	// turn off the SPI device (i.e., slave) interface controller
	SPID_CFG &= ~0x01;

	/* disable unused clock domains */
	CLKEN_1 &= 0xe5;  // no SPI slave, no SMBus, no LSIBM, but leave EDI!
#ifdef NO_PS2
	CLKEN_2 &= 0x50;  // no PS/2, IKB, digital samplers, CIR, or CEC
#else
	CLKEN_2 &= 0xd0;  // no IKB, digital samplers, CIR, or CEC
#endif
	CLKEN_3 &= 0xe1;  // no SMBus
	CLKEN_4 &= 0x01;  // no CEC

	output_enable_LV_SET();

}

void init_board_rev(void)
{
	switch (board_rev)
	{
		case 0xb1:
			puts("B1 PROTO");
			break;

		case 0xb2:
			puts("B1 PROTO w/DCON");
			break;

		case 0xb3:
			puts("B1 PROTO Plimit mod");
			break;

		case 0xb4:
			puts("B1 proto experimental");
			break;

		case 0xc1:
			puts("C1 PROTO");
			break;

		case 0xc2:
			puts("C2 RAMP");
			break;

		case 0x0a1:
			puts("A1 mmp2");
			break;

		case 0x0a2:
		case 0x0a3:
			puts("A2/A3 unsupp");
		default:
			printf("\n !!!ERROR!!! No defaults set for Rev 0x%x\n",(unsigned int)board_rev);
			break;
	}
}


int adc_to_eighths(unsigned char channel)
{
	// (assumes 8-bit ADC value)
	// 8 resistors give 8 IDs, but because of "bucketing":
	// up to 0x30 is 1, up to 0x50 is 2, etc,...
	// up to 0xd0 is 6, up to 0xf0 is 7, then 8
	unsigned int id;

	// get a couple of 8-bit adc readings, and average
	id = read_ad_ch_8(channel);
	id += read_ad_ch_8(channel);
	id /= 2;

	// convert to 8ths
	id += 0x10;
	id /= 32;

	if (id == 0) id = 1; // merge the 0 and 1 buckets

	// the return value is between 1 and 8 inclusive, no 0.
	// this corresponds to the h/w notion of 1/8, 2/8, etc.
	return id;
}

// the resistors (and this table) allow for 64 different 2-byte
// board ids.  3 bits come from each resistor value.
code unsigned int id_values[] =
{
	0xA1, 0xA2, 0xA3, 0xB1, 0xB2, 0xB3, 0xB4, 0x00,	//  id1 == 1/8
	0xC1, 0xC2, // 0x00,  0x00,  0x00,  0x00, 0x00, 0x00,	//  id1 == 2/8
};

// Read the rev of the board from the AD converter.
void get_board_id(void)
{
	unsigned char id0, id1, index;

	id0 = adc_to_eighths(ADC_EC_ID0) - 1;
	id1 = adc_to_eighths(ADC_EC_ID1) - 1;

	index = (id1 << 3) | id0;
	if (index > (sizeof(id_values)/sizeof(id_values[0])) - 1)
		board_rev = 0;
	else
		board_rev = id_values[index];

	printf("Setting Board Rev %x\n",(unsigned int)board_rev);

}

void uart_io_init(void)
{
	// Make pin TX output
	IO_ALT_OUT_ENABLE(GPIO_1E);
	IO_OUTPUT_ENABLE(GPIO_1E);
	// Don't enable the input pin Alt out
	// or it won't work.
	IO_INPUT_ONLY(GPIO_1D);

}

#ifndef NO_PS2
void ps2_io_init(void)
{
	// PS2 is bi-dirctional on both pins
	// Input enables are required.

	// Touchpad
	IO_ALT_OUT_ENABLE(GPIO_35);
	IO_INPUT_ENABLE(GPIO_35);
	IO_ALT_OUT_ENABLE(GPIO_36);
	IO_INPUT_ENABLE(GPIO_36);

	// Select PS2 function rather than I2C
	// bit 0x01 is a reserved bit that was set in
	// EnE example code.
	MFPCTRL = 0x04;

	// Keyboard
	IO_ALT_OUT_ENABLE(GPIO_37);
	IO_INPUT_ENABLE(GPIO_37);
	IO_ALT_OUT_ENABLE(GPIO_38);
	IO_INPUT_ENABLE(GPIO_38);

	// Enable the ps2 interrupt channel
	P0IE2 = 1;
}
#endif

void leds_init(void)
{
	set_LED_PWR_off();
	output_enable_LED_PWR();
	input_enable_LED_PWR();

	// TODO: Turn these back into PWM signals
	set_LED_CHG_GREEN_off();
	set_LED_CHG_RED_off();

	output_enable_LED_CHG_GREEN();
	output_enable_LED_CHG_RED();

}

void set_LV_SET(unsigned char value)
{
	if ( board_rev > 0xb2 || board_rev == 0xa1 )
	{
		// Haven't seen a need for 12 bits of resolution yet so
		// just scale the 8bit value up.
		set_pwm(2,(((unsigned int)value)<<4));
	}
	else
	{
		DAC0 = value;
	}
}

// The datasheet isn't very clear on the enable. In the special
// function table there is a note that if the DAC is enabled then
// don't set this bit. They are referring to the GPO output bit.

void output_enable_LV_SET(void)
{
	if (board_rev > 0xb2 || board_rev == 0xa1 )
	{
		pwm_2_init();
	}
	else
	{
		DAC0 = 0;
		ADDAEN |= 0x40;
		IO_ALT_OUT_ENABLE(GPIO_0E);
	}
}

#ifdef UNUSED
void output_disable_LV_SET(void)
{
	if (board_rev > 0xb2 || board_rev == 0xa1 )
	{
		IO_ALT_OUT_DISABLE(GPIO_15);
		IO_OUTPUT_DISABLE(GPIO_15);
	}
	else
	{
		// Datasheet says make sure this is zero before disableing
		DAC0 = 0;
		ADDAEN &= ~0x40;
		IO_ALT_OUT_DISABLE(GPIO_0E);
		IO_OUTPUT_DISABLE(GPIO_0E);
	}
}
#endif
